/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 abel533@gmail.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.hicoffee.bm.service.impl;

import com.hicoffee.bm.model.BaseModel;
import com.hicoffee.bm.service.IService;
import com.radarwin.framework.util.StringUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.entity.Example;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Duke on 2017/4/11.
 */
public abstract class BaseService<T> implements IService<T> {

    protected Logger logger = LogManager.getLogger(this.getClass());

    protected Class genericClass = (Class) ((ParameterizedType) getClass()
            .getGenericSuperclass()).getActualTypeArguments()[0];

    protected Map<Class, Class> classCache = new HashMap<>();


    @Autowired
    protected Mapper<T> mapper;

    public Mapper<T> getMapper() {
        return mapper;
    }

    @Override
    public T selectByKey(Object key) {
        return mapper.selectByPrimaryKey(key);
    }

    public int save(T entity) {
        return mapper.insert(entity);
    }

    public int delete(Object key) {
        return mapper.deleteByPrimaryKey(key);
    }

    public int updateAll(T entity) {
        return mapper.updateByPrimaryKey(entity);
    }

    public int updateNotNull(T entity) {
        return mapper.updateByPrimaryKeySelective(entity);
    }

    public List<T> selectByExample(Object example) {
        return mapper.selectByExample(example);
    }


    @Override
    public int selectCountByExample(Object example) {
        return mapper.selectCountByExample(example);
    }

    @Override
    public List<T> selectByMap(Map<String, Object> search) {
        Example example = new Example(genericClass);
        Example.Criteria criteria = example.createCriteria();
        for (Map.Entry<String, Object> entry : search.entrySet()) {
            criteria.andEqualTo(entry.getKey(), entry.getValue());
        }
        return mapper.selectByExample(example);
    }

    /**
     * 为其四要素注入值
     *
     * @param t
     * @return
     */
    @Override
    public int insert(T t) {
        Class supperClass = t.getClass().getSuperclass();
        if (supperClass != null) {
            if (supperClass.equals(BaseModel.class) ||
                    supperClass.equals(com.radarwin.framework.model.BaseModel.class)) {

                Method[] methodsOfBaseModel = supperClass.getMethods();
                Date now = new Date();
                for (Method method : methodsOfBaseModel) {
                    try {
                        switch (method.getName()) {
                            case "setCreateUser":
//                                method.invoke(t, UserUtil.getUserToken());
                                break;
                            case "setCreateTime":
                                method.invoke(t, now);
                                break;
                            case "setUpdateUser":
//                                method.invoke(t, UserUtil.getUserToken());
                                break;
                            case "setUpdateTime":
                                method.invoke(t, now);
                                break;
                            case "setDeleted":
                                method.invoke(t, false);
                                break;

                        }
                    } catch (Exception e) {
                        logger.error(e);

                    }
                }
            }

        }
        return mapper.insert(t);
    }


    /**
     * 为其 updateUser updateTime 注入值
     *
     * @param entity
     * @return
     */
    @Override
    public int update(T entity) {
        Class supperClass = entity.getClass().getSuperclass();
        if (supperClass != null) {
            if (supperClass.equals(BaseModel.class) ||
                    supperClass.equals(com.radarwin.framework.model.BaseModel.class)) {
                Method[] methodsOfBaseModel = supperClass.getMethods();
                Date now = new Date();
                for (Method method : methodsOfBaseModel) {
                    try {
                        switch (method.getName()) {
                            case "setUpdateUser":
                                method.invoke(entity, "代码写死需要修改");
                                break;
                            case "setUpdateTime":
                                method.invoke(entity, now);
                                break;
                        }
                    } catch (Exception e) {
                        logger.error(e);

                    }
                }
            }

        }
        return mapper.updateByPrimaryKeySelective(entity);
    }

    @Override
    public int logicDelete(String ids) {
        int result = 0;
        if (StringUtil.isNoneBlank(ids)) {
            try {
                Object entity = genericClass.newInstance();
                Class supperClass = genericClass.getSuperclass();
                String[] idsAsArray = ids.split(",");
                for (String id : idsAsArray) {
                    if (supperClass.equals(BaseModel.class) ||
                            supperClass.equals(com.radarwin.framework.model.BaseModel.class)) {
                        Method[] methods = genericClass.getMethods();
                        for (Method method : methods) {
                            switch (method.getName()) {
                                case "setId":
                                    method.invoke(entity, Long.valueOf(id));
                                    break;
                                case "setDeleted":
                                    method.invoke(entity, true);
                                    break;
                            }
                        }
                        result = update((T) entity);
                        if (result < 0) {
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                logger.error("logic delete error :", e);
                throw new RuntimeException("logic delete error :", e);
            }
        }
        return result;
    }

}
